#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define hex_buffer_length (80)
#define bin_buffer_length (hex_buffer_length * 8 + 1)

unsigned char hex_data[hex_buffer_length] = {
    0x4D, 0xC0, 0xE1, 0x8F, 0x91, 0x50, 0x03, 0xE8, 0xD9, 0xEE, 0x6C, 0x8A, 0x19, 0xE9, 0x08, 0x00,
    0x19, 0xEA, 0x04, 0x00, 0x5F, 0xA8, 0x05, 0x80, 0x60, 0x9A, 0x1D, 0x10, 0xF2, 0x5C, 0x91, 0x40,
    0x03, 0xC8, 0x99, 0xCC, 0xAC, 0xDD, 0x30, 0xCE, 0x3C, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x91, 0x30, 0x00, 0xFF, 0xD9, 0xFF, 0x10, 0x16, 0x48, 0x02, 0x07, 0x22, 0x04, 0x22, 0x00, 0x90
};
unsigned  char binaryString[bin_buffer_length]; // Each hex digit converts to 4 binary digits, so 2 hex digits => 8 binary digits
// Convert binary string back to hexadecimal
unsigned  char convertedHexString[hex_buffer_length]; // 2 binary digits => 1 hex digit

// Function to convert a 4-bit binary string to hexadecimal
unsigned char binaryToHexDigit(const char* binaryDigit) {
    if (strcmp(binaryDigit, "0000") == 0) return 0x0;
    else if (strcmp(binaryDigit, "0001") == 0) return 0x1;
    else if (strcmp(binaryDigit, "0010") == 0) return 0x2;
    else if (strcmp(binaryDigit, "0011") == 0) return 0x3;
    else if (strcmp(binaryDigit, "0100") == 0) return 0x4;
    else if (strcmp(binaryDigit, "0101") == 0) return 0x5;
    else if (strcmp(binaryDigit, "0110") == 0) return 0x6;
    else if (strcmp(binaryDigit, "0111") == 0) return 0x7;
    else if (strcmp(binaryDigit, "1000") == 0) return 0x8;
    else if (strcmp(binaryDigit, "1001") == 0) return 0x9;
    else if (strcmp(binaryDigit, "1010") == 0) return 0xA;
    else if (strcmp(binaryDigit, "1011") == 0) return 0xB;
    else if (strcmp(binaryDigit, "1100") == 0) return 0xC;
    else if (strcmp(binaryDigit, "1101") == 0) return 0xD;
    else if (strcmp(binaryDigit, "1110") == 0) return 0xE;
    else if (strcmp(binaryDigit, "1111") == 0) return 0xF;
    else return 0xFF; // Invalid binary digit
}

// Function to convert a binary string to hexadecimal
void binaryToHexString(const unsigned char* binaryString, unsigned char* hexString) {
    int length = 0;
    while (binaryString[length] != '\0') {
        length++;
    }

    // Ensure the binary string length is a multiple of 4
    int padding = (4 - (length % 4)) % 4;
    int totalLength = length + padding;

    char paddedBinaryString[totalLength + 1];
    strncpy(paddedBinaryString, binaryString, bin_buffer_length);

    // Pad with leading zeros
    for (int i = length; i < totalLength; i++) {
        paddedBinaryString[i] = '0';
    }
    paddedBinaryString[totalLength] = '\0';

    int hexIndex = 0;
    for (int i = 0; i < totalLength; i += 4) {
        char binaryDigit[5];
        strncpy(binaryDigit, paddedBinaryString + i, 4);
        binaryDigit[4] = '\0';

        unsigned char hexDigit = binaryToHexDigit(binaryDigit);
        if (hexDigit != 0xFF) {
            if (i%8==0)
            {
                hexString[hexIndex] |= hexDigit<<4;
            }
            else
            {
                hexString[hexIndex++] += hexDigit;
            }
        }
    }

    // hexString[hexIndex] = '\0';
}

// Function to convert a hexadecimal digit to binary
void hexToBinary(unsigned char hexDigit, char *OutBinaryHigh, char *OutBinaryLow) {
    switch (hexDigit >> 4) {
        case 0x0: strncpy(OutBinaryHigh, "0000" ,4); break;
        case 0x1: strncpy(OutBinaryHigh, "0001" ,4); break;
        case 0x2: strncpy(OutBinaryHigh, "0010" ,4); break;
        case 0x3: strncpy(OutBinaryHigh, "0011" ,4); break;
        case 0x4: strncpy(OutBinaryHigh, "0100" ,4); break;
        case 0x5: strncpy(OutBinaryHigh, "0101" ,4); break;
        case 0x6: strncpy(OutBinaryHigh, "0110" ,4); break;
        case 0x7: strncpy(OutBinaryHigh, "0111" ,4); break;
        case 0x8: strncpy(OutBinaryHigh, "1000" ,4); break;
        case 0x9: strncpy(OutBinaryHigh, "1001" ,4); break;
        case 0xA: strncpy(OutBinaryHigh, "1010" ,4); break;
        case 0xB: strncpy(OutBinaryHigh, "1011" ,4); break;
        case 0xC: strncpy(OutBinaryHigh, "1100" ,4); break;
        case 0xD: strncpy(OutBinaryHigh, "1101" ,4); break;
        case 0xE: strncpy(OutBinaryHigh, "1110" ,4); break;
        case 0xF: strncpy(OutBinaryHigh, "1111" ,4); break;
        default: strncpy(OutBinaryHigh, "0000" ,4); break;
    }

    switch (hexDigit & 0x0F) {
        case 0x0: strncpy(OutBinaryLow, "0000" ,4); break;
        case 0x1: strncpy(OutBinaryLow, "0001" ,4); break;
        case 0x2: strncpy(OutBinaryLow, "0010" ,4); break;
        case 0x3: strncpy(OutBinaryLow, "0011" ,4); break;
        case 0x4: strncpy(OutBinaryLow, "0100" ,4); break;
        case 0x5: strncpy(OutBinaryLow, "0101" ,4); break;
        case 0x6: strncpy(OutBinaryLow, "0110" ,4); break;
        case 0x7: strncpy(OutBinaryLow, "0111" ,4); break;
        case 0x8: strncpy(OutBinaryLow, "1000" ,4); break;
        case 0x9: strncpy(OutBinaryLow, "1001" ,4); break;
        case 0xA: strncpy(OutBinaryLow, "1010" ,4); break;
        case 0xB: strncpy(OutBinaryLow, "1011" ,4); break;
        case 0xC: strncpy(OutBinaryLow, "1100" ,4); break;
        case 0xD: strncpy(OutBinaryLow, "1101" ,4); break;
        case 0xE: strncpy(OutBinaryLow, "1110" ,4); break;
        case 0xF: strncpy(OutBinaryLow, "1111" ,4); break;
        default: strncpy(OutBinaryLow, "0000" ,4); break;
    }
}

// Function to convert a hexadecimal array to binary string
void hexArrayToBinaryString(const unsigned char* hexArray, int length, char* binaryString) {
    int binaryIndex = 0;
    for (int i = 0; i < length; i++) {
        char binaryHigh[5], binaryLow[5];
        hexToBinary(hexArray[i], binaryHigh, binaryLow);

        // Append binary representations to the binary string
        for (int j = 0; j < 4; j++) {
            binaryString[binaryIndex++] = binaryHigh[j];
        }
        for (int j = 0; j < 4; j++) {
            binaryString[binaryIndex++] = binaryLow[j];
        }
    }

    binaryString[binaryIndex] = '\0';
}

int main() {
    printf("Hexadecimal: ");
    for (int i = 0; i < hex_buffer_length; i++) {
        printf("%02X ", hex_data[i]);
    }
    printf("\n");

    // Convert hexadecimal array to binary string
    hexArrayToBinaryString(hex_data, hex_buffer_length, binaryString);
    printf("Binary: ");
    for (int i = 0; i < bin_buffer_length; i++) {
        printf("%c", binaryString[i]);
    }
    printf("\n");

    binaryToHexString(binaryString, convertedHexString);
    // printf("Converted Hexadecimal: %s\n", convertedHexString);
    printf("Converted Hexadecimal: ");
    for (int i = 0; i < hex_buffer_length; i++) {
        printf("%02X ", convertedHexString[i]);
    }
    printf("\n");

    return 0;
}
